import subprocess
import re
import platform
import os
from datetime import datetime
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QTableWidgetItem, QHeaderView
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from qfluentwidgets import (
    CardWidget, BodyLabel, StrongBodyLabel, TitleLabel, LineEdit,
    FluentIcon, InfoBar, InfoBarPosition, ScrollArea, ComboBox,
    PrimaryPushButton, TableWidget, PushButton
)
from PyQt6.QtGui import QColor, QFont
from common.widgets.info_card import InfoCard
# Removed reportlab import as it's no longer needed for TXT export
# from reportlab.lib.pagesizes import A4
# from reportlab.pdfgen import canvas


class UserScanThread(QThread):
    scan_completed = pyqtSignal(list)
    progress_updated = pyqtSignal(int)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.user_data = []
        self.min_password_length = "未知"

    def run(self):
        try:
            self.user_data = self.get_user_info()
            total = len(self.user_data)
            for i, _ in enumerate(self.user_data):
                self.progress_updated.emit(int((i + 1) / total * 100))
            self.scan_completed.emit([])
        except Exception as e:
            self.scan_completed.emit([f"扫描失败: {str(e)}"])

    def get_user_info(self):
        try:
            # 获取系统密码长度策略
            try:
                result = subprocess.run(['net', 'accounts'], capture_output=True, text=True, encoding='gbk')
                if result.returncode == 0:
                    for line in result.stdout.splitlines():
                        # 匹配中文或英文输出
                        length_match = re.search(r'最小密码长度[:\s]+(\d+)|Minimum password length[:\s]+(\d+)', line,
                                                 re.IGNORECASE)
                        if length_match:
                            self.min_password_length = f"{length_match.group(1) or length_match.group(2)} 位"
                            break
                    else:
                        self.min_password_length = "未设置"
            except:
                self.min_password_length = "检查失败"

            result = subprocess.run(['net', 'user'], capture_output=True, text=True, encoding='gbk')
            if result.returncode != 0:
                return []

            users = []
            user_section = False
            for line in result.stdout.splitlines():
                if line.startswith('---'):
                    user_section = True
                    continue
                if user_section and line.strip() and '命令成功完成' not in line:
                    users.extend(line.strip().split())

            user_data = []
            for user in users:
                try:
                    user_info = subprocess.run(['net', 'user', user], capture_output=True, text=True, encoding='gbk')
                    if user_info.returncode != 0:
                        continue

                    info = user_info.stdout
                    enabled = "启用" if "帐户启用               Yes" in info else "禁用"

                    admin_check = subprocess.run(['net', 'localgroup', 'Administrators'],
                                                 capture_output=True, text=True, encoding='gbk')
                    is_admin = "是" if user in admin_check.stdout else "否"

                    last_logon_match = re.search(r'上次登录\s+(.+)', info)
                    last_logon = last_logon_match.group(1).strip() if last_logon_match else "未知"

                    password_expires = "是" if "密码过期时间                 从不" not in info else "否"

                    has_empty_password = "是" if "密码请求                   否" in info else "否"
                    risk_level = self.assess_user_risk(user, enabled, is_admin, last_logon, info)

                    user_data.append({
                        'username': user,
                        'status': enabled,
                        'is_admin': is_admin,
                        'last_logon': last_logon,
                        'password_expires': password_expires,
                        'has_empty_password': has_empty_password,
                        'risk_level': risk_level,
                        'min_password_length': self.min_password_length,
                        'full_info': info
                    })
                except Exception:
                    continue
            return user_data
        except Exception:
            return []


    def assess_user_risk(self, username, status, is_admin, last_logon, full_info):
        risk_score = 0
        if is_admin == "是":
            risk_score += 3
        if status == "启用" and "从不" in last_logon:
            risk_score += 2
        if "密码过期时间                 从不" in full_info:
            risk_score += 2
        if "锁定阈值                 从不" in full_info:
            risk_score += 1
        if "密码请求                   否" in full_info:
            risk_score += 2
        try:
            if platform.system() == "Windows":
                result = subprocess.run(['net', 'accounts'], capture_output=True, text=True, encoding='gbk')
                if "最小密码长度                 0" in result.stdout:
                    risk_score += 2
        except:
            pass

        if risk_score >= 5:
            return "高风险"
        elif risk_score >= 3:
            return "中风险"
        else:
            return "低风险"


class UserManager(QWidget):
    def __init__(self):
        super().__init__()
        self.user_data = []
        self.security_risks = []
        self.init_ui()
        self.update_user_data()

    def init_ui(self):
        scroll_area = ScrollArea(self)
        scroll_widget = QWidget()
        scroll_area.setWidget(scroll_widget)
        scroll_area.setWidgetResizable(True)
        scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)

        main_layout = QVBoxLayout(self)
        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.addWidget(scroll_area)

        content_layout = QVBoxLayout(scroll_widget)
        content_layout.setContentsMargins(30, 30, 30, 30)
        content_layout.setSpacing(20)

        header_layout = QHBoxLayout()
        title = TitleLabel("用户权限安全审查")
        header_layout.addWidget(title)
        header_layout.addStretch()

        self.refresh_btn = PushButton("刷新", self)
        self.refresh_btn.setIcon(FluentIcon.SYNC)
        self.refresh_btn.clicked.connect(self.update_user_data)
        header_layout.addWidget(self.refresh_btn)

        self.export_btn = PushButton("导出报告", self)
        self.export_btn.setIcon(FluentIcon.SAVE)
        self.export_btn.clicked.connect(self.export_report)
        header_layout.addWidget(self.export_btn)

        content_layout.addLayout(header_layout)

        stats_card = CardWidget()
        stats_layout = QVBoxLayout(stats_card)
        stats_layout.setContentsMargins(20, 20, 20, 20)
        stats_layout.setSpacing(15)

        stats_header = QHBoxLayout()
        stats_title = StrongBodyLabel("账户统计")
        stats_title.setFont(QFont("Microsoft YaHei", 14))
        stats_header.addWidget(stats_title)
        stats_header.addStretch()
        stats_layout.addLayout(stats_header)

        self.total_users_card = InfoCard("总用户", "0", "个", "👥", "#0078D7")
        self.enabled_users_card = InfoCard("启用账户", "0", "个", "✅", "#27ae60")
        self.admin_users_card = InfoCard("管理员", "0", "个", "🔒", "#f39c12")
        self.high_risk_users_card = InfoCard("高风险", "0", "个", "⚠️", "#e74c3c")

        stats_grid = QGridLayout()
        stats_grid.addWidget(self.total_users_card, 1, 0)
        stats_grid.addWidget(self.enabled_users_card, 1, 1)
        stats_grid.addWidget(self.admin_users_card, 1, 2)
        stats_grid.addWidget(self.high_risk_users_card, 1, 3)
        stats_layout.addLayout(stats_grid)

        content_layout.addWidget(stats_card)

        filter_layout = QHBoxLayout()
        self.search_input = LineEdit()
        self.search_input.setPlaceholderText("搜索用户...")
        self.search_input.setFixedWidth(200)
        self.search_input.textChanged.connect(self.filter_users)
        filter_layout.addWidget(self.search_input)

        self.filter_combo = ComboBox()
        self.filter_combo.addItems(["全部", "启用账户", "管理员账户", "高风险账户"])
        self.filter_combo.setFixedWidth(150)
        self.filter_combo.currentIndexChanged.connect(self.filter_users)
        filter_layout.addWidget(self.filter_combo)
        filter_layout.addStretch()
        content_layout.addLayout(filter_layout)

        user_card = CardWidget()
        user_layout = QVBoxLayout(user_card)
        user_layout.setContentsMargins(20, 20, 20, 20)
        user_layout.setSpacing(15)

        user_header = QHBoxLayout()
        user_title = StrongBodyLabel("用户账户列表")
        user_title.setFont(QFont("Microsoft YaHei", 14))
        self.user_count_label = BodyLabel("(0 个用户)")
        user_header.addWidget(user_title)
        user_header.addWidget(self.user_count_label)
        user_header.addStretch()
        user_layout.addLayout(user_header)

        self.user_table = TableWidget()
        self.user_table.setColumnCount(5)
        self.user_table.setHorizontalHeaderLabels(["用户名", "状态", "管理员", "最后登录", "风险等级"])
        self.user_table.setSelectionBehavior(TableWidget.SelectionBehavior.SelectRows)
        self.user_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        self.user_table.setSortingEnabled(True)
        self.user_table.setMinimumHeight(300)
        user_layout.addWidget(self.user_table)

        content_layout.addWidget(user_card)

        detail_card = CardWidget()
        detail_layout = QVBoxLayout(detail_card)
        detail_layout.setContentsMargins(15, 15, 15, 15)
        detail_layout.setSpacing(20)

        detail_title = StrongBodyLabel("权限详细信息")
        detail_title.setFont(QFont("Microsoft YaHei", 14))
        detail_layout.addWidget(detail_title)

        self.detail_table = TableWidget()
        self.detail_table.setColumnCount(3)
        self.detail_table.setHorizontalHeaderLabels(["权限项目", "当前状态", "安全建议"])
        self.detail_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        self.detail_table.setMinimumHeight(200)
        detail_layout.addWidget(self.detail_table)

        content_layout.addWidget(detail_card)

    def update_user_data(self):
        """更新用户数据"""
        self.scan_thread = UserScanThread(self)
        self.scan_thread.scan_completed.connect(self.on_scan_completed)
        self.scan_thread.progress_updated.connect(self.update_scan_progress)
        self.scan_thread.start()

    def update_scan_progress(self, progress):
        """更新扫描进度"""
        pass

    def on_scan_completed(self, risks):
        """扫描完成处理"""
        self.user_data = self.scan_thread.user_data
        self.security_risks = risks
        self.update_table()
        self.update_statistics()
        self.update_detail_info()

        InfoBar.success(
            title="更新完成",
            content="用户数据已刷新",
            orient=Qt.Orientation.Horizontal,
            isClosable=True,
            position=InfoBarPosition.TOP_RIGHT,
            duration=2000,
            parent=self
        )

    def update_table(self):
        """更新用户表格"""
        self.user_table.setRowCount(0)
        filter_text = self.search_input.text().lower()
        filter_type = self.filter_combo.currentText()

        for user in self.user_data:
            if filter_text and filter_text not in user['username'].lower():
                continue
            if filter_type == "启用账户" and user['status'] != "启用":
                continue
            if filter_type == "管理员账户" and user['is_admin'] != "是":
                continue
            if filter_type == "高风险账户" and user['risk_level'] != "高风险":
                continue

            row = self.user_table.rowCount()
            self.user_table.insertRow(row)

            user_item = QTableWidgetItem(user['username'])
            user_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
            self.user_table.setItem(row, 0, user_item)

            status_item = QTableWidgetItem(user['status'])
            status_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
            status_item.setForeground(QColor("#27ae60" if user['status'] == "启用" else "#e74c3c"))
            self.user_table.setItem(row, 1, status_item)

            admin_item = QTableWidgetItem(user['is_admin'])
            admin_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
            admin_item.setForeground(QColor("#f39c12" if user['is_admin'] == "是" else "#666666"))
            self.user_table.setItem(row, 2, admin_item)

            last_login = QTableWidgetItem(user['last_logon'])
            last_login.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
            self.user_table.setItem(row, 3, last_login)

            risk_item = QTableWidgetItem(user['risk_level'])
            risk_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
            if user['risk_level'] == "高风险":
                risk_item.setForeground(QColor("#e74c3c"))
            elif user['risk_level'] == "中风险":
                risk_item.setForeground(QColor("#f39c12"))
            else:
                risk_item.setForeground(QColor("#27ae60"))
            self.user_table.setItem(row, 4, risk_item)

        row_height = self.user_table.rowHeight(0) if self.user_table.rowCount() > 0 else 30
        header_height = self.user_table.horizontalHeader().height()
        total_height = header_height + (row_height * self.user_table.rowCount()) + 50
        self.user_table.setMinimumHeight(min(total_height, 600))

    def update_statistics(self):
        """更新统计信息"""
        total = len(self.user_data)
        enabled = sum(1 for u in self.user_data if u['status'] == "启用")
        admins = sum(1 for u in self.user_data if u['is_admin'] == "是")
        high_risk = sum(1 for u in self.user_data if u['risk_level'] == "高风险")

        self.user_count_label.setText(f"({total} 个用户)")
        self.total_users_card.update_value(str(total), "个")
        self.enabled_users_card.update_value(str(enabled), "个")
        self.admin_users_card.update_value(str(admins), "个")
        self.high_risk_users_card.update_value(str(high_risk), "个")

    def update_detail_info(self):
        """更新权限详情表格"""
        self.detail_table.setRowCount(0)

        empty_password_count = sum(1 for u in self.user_data if u.get('has_empty_password', '否') == '是')
        min_password_length = self.user_data[0].get('min_password_length', '未知') if self.user_data else '未知'

        permissions = [
            ("管理员账户数量", f"{sum(1 for u in self.user_data if u['is_admin'] == '是')} 个",
             "建议最小化管理员账户数量，定期审查"),
            ("启用的空密码账户", f"{empty_password_count} 个",
             "应设置强密码（至少8位，包含字母、数字、符号）"),
            ("长期未登录账户",
             f"{sum(1 for u in self.user_data if '从不' in u['last_logon'] and u['status'] == '启用')} 个",
             "建议禁用超过90天未登录的账户"),
            ("密码永不过期账户",
             f"{sum(1 for u in self.user_data if u.get('password_expires', '否') == '否')} 个",
             "建议设置30-90天的密码过期策略"),
            ("密码长度策略", min_password_length,
             "建议最低密码长度为8位")
        ]

        for i, (item, status, advice) in enumerate(permissions):
            self.detail_table.insertRow(i)
            item_table = QTableWidgetItem(item)
            item_table.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
            self.detail_table.setItem(i, 0, item_table)

            status_table = QTableWidgetItem(status)
            status_table.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
            self.detail_table.setItem(i, 1, status_table)

            advice_table = QTableWidgetItem(advice)
            advice_table.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
            self.detail_table.setItem(i, 2, advice_table)

        row_height = self.detail_table.rowHeight(0) if self.detail_table.rowCount() > 0 else 30
        header_height = self.detail_table.horizontalHeader().height()
        total_height = header_height + (row_height * self.detail_table.rowCount()) + 50
        self.detail_table.setMinimumHeight(total_height)

    def filter_users(self):
        """过滤用户列表"""
        self.update_table()

    def export_report(self):
        """导出安全审查报告为 TXT"""
        try:
            # Change file extension to .txt
            filename = f"user_security_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"

            report_content = []
            report_content.append("用户权限安全审查报告")
            report_content.append(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
            report_content.append(f"操作系统: {platform.system()} {platform.release()}")
            report_content.append(f"主机名: {platform.node()}")
            report_content.append("\n账户统计:")
            report_content.append(f"  总用户: {len(self.user_data)} 个")
            report_content.append(f"  启用账户: {sum(1 for u in self.user_data if u['status'] == '启用')} 个")
            report_content.append(f"  管理员账户: {sum(1 for u in self.user_data if u['is_admin'] == '是')} 个")
            report_content.append(f"  高风险账户: {sum(1 for u in self.user_data if u['risk_level'] == '高风险')} 个")

            report_content.append("\n权限详情:")
            min_password_length = self.user_data[0].get('min_password_length', '未知') if self.user_data else '未知'
            permissions = [
                ("管理员账户数量", f"{sum(1 for u in self.user_data if u['is_admin'] == '是')} 个",
                 "建议最小化管理员账户数量"),
                ("启用的空密码账户", f"{sum(1 for u in self.user_data if u.get('has_empty_password', '否') == '是')} 个",
                 "应设置强密码"),
                ("长期未登录账户",
                 f"{sum(1 for u in self.user_data if '从不' in u['last_logon'] and u['status'] == '启用')} 个",
                 "建议禁用超过90天未登录的账户"),
                ("密码永不过期账户", f"{sum(1 for u in self.user_data if u.get('password_expires', '否') == '否')} 个",
                 "建议设置30-90天的密码过期策略"),
                ("密码长度策略", min_password_length,
                 "建议最低密码长度为8位")
            ]
            for item, status, advice in permissions:
                report_content.append(f"  {item}: {status} ({advice})")

            report_content.append("\n用户账户列表:")
            # Add table header for clarity in TXT
            report_content.append(f"{'用户名':<20}{'状态':<10}{'管理员':<10}{'最后登录':<20}{'风险等级':<10}")
            report_content.append("-" * 75) # Separator
            for user in self.user_data:
                report_content.append(
                    f"{user['username']:<20}"
                    f"{user['status']:<10}"
                    f"{user['is_admin']:<10}"
                    f"{user['last_logon']:<20}"
                    f"{user['risk_level']:<10}"
                )

            # Write content to the text file
            with open(filename, 'w', encoding='utf-8') as f:
                for line in report_content:
                    f.write(line + '\n')

            InfoBar.success(
                title="导出成功",
                content=f"报告已保存为 {filename}",
                position=InfoBarPosition.TOP_RIGHT,
                duration=3000,
                parent=self
            )
        except Exception as e:
            InfoBar.error(
                title="导出失败",
                content=str(e),
                position=InfoBarPosition.TOP_RIGHT,
                duration=3000,
                parent=self
            )